package com.fancy.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.http.HttpMethod;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Spring Security配置类 - 基于Spring WebFlux响应式架构
 * 适配在线音乐平台的微服务架构和用户权限体系
 *
 * @author fancy
 */
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    /**
     * 密码编码器 - 用于用户密码加密
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * CORS跨域配置 - 支持前端访问
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();

        // 允许的源地址（生产环境应配置具体域名）
        configuration.setAllowedOriginPatterns(Collections.singletonList("*"));

        // 允许的HTTP方法
        configuration.setAllowedMethods(Arrays.asList(
            HttpMethod.GET.name(),
            HttpMethod.POST.name(),
            HttpMethod.PUT.name(),
            HttpMethod.DELETE.name(),
            HttpMethod.OPTIONS.name(),
            HttpMethod.PATCH.name()
        ));

        // 允许的请求头
        configuration.setAllowedHeaders(Arrays.asList(
            "Authorization",
            "Content-Type",
            "X-Requested-With",
            "Accept",
            "Origin",
            "Access-Control-Request-Method",
            "Access-Control-Request-Headers",
            "X-User-Id",
            "X-Username",
            "X-User-Role"
        ));

        // 允许携带凭证
        configuration.setAllowCredentials(true);

        // 暴露给前端的响应头
        configuration.setExposedHeaders(Arrays.asList(
            "Authorization",
            "X-User-Id",
            "X-Username",
            "X-User-Role",
            "X-Membership-Type",
            "X-Is-Vip",
            "Content-Length",
            "Content-Range"
        ));

        // 预检请求的缓存时间
        configuration.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    /**
     * Security过滤器链配置 - 基于WebFlux响应式
     */
    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        return http
            // 禁用CSRF（微服务架构下使用JWT，不需要CSRF保护）
            .csrf(ServerHttpSecurity.CsrfSpec::disable)

            // 启用CORS
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))

            // 禁用表单登录和HTTP基础认证
            .formLogin(ServerHttpSecurity.FormLoginSpec::disable)
            .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)

            // 禁用Session（使用JWT无状态认证）
            .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())

            // 配置请求授权规则
            .authorizeExchange(exchanges -> exchanges
                // 公开接口 - 无需认证
                .pathMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .pathMatchers("/actuator/**").permitAll()
                .pathMatchers("/favicon.ico").permitAll()

                // 用户认证相关接口 - 无需认证
                .pathMatchers(HttpMethod.POST, "/api/v1/users/login").permitAll()
                .pathMatchers(HttpMethod.POST, "/api/v1/users/register").permitAll()
                .pathMatchers(HttpMethod.POST, "/api/v1/auth/refresh").permitAll()
                .pathMatchers(HttpMethod.POST, "/api/v1/auth/logout").permitAll()
                .pathMatchers(HttpMethod.POST, "/api/v1/users/forgot-password").permitAll()
                .pathMatchers(HttpMethod.POST, "/api/v1/users/reset-password").permitAll()
                .pathMatchers(HttpMethod.GET, "/api/v1/users/verify-email").permitAll()

                // 公开的音乐接口 - 游客可访问
                .pathMatchers(HttpMethod.GET, "/api/v1/songs/public/**").permitAll()
                .pathMatchers(HttpMethod.GET, "/api/v1/artists/public/**").permitAll()
                .pathMatchers(HttpMethod.GET, "/api/v1/albums/public/**").permitAll()
                .pathMatchers(HttpMethod.GET, "/api/v1/rankings/public/**").permitAll()

                // 公开的推荐接口
                .pathMatchers(HttpMethod.GET, "/api/v1/recommendations/hot").permitAll()
                .pathMatchers(HttpMethod.GET, "/api/v1/rankings/hot").permitAll()

                // 文件上传下载接口
                .pathMatchers("/api/v1/files/upload/**").authenticated()
                .pathMatchers(HttpMethod.GET, "/api/v1/files/download/**").permitAll()

                // 管理员接口 - 需要管理员权限（由AdminAuthenticationFilter处理）
                .pathMatchers("/api/v1/admin/**").permitAll()

                // VIP专享接口 - 需要VIP权限（由AuthenticationFilter检查VIP权限）
                .pathMatchers("/api/v1/songs/vip/**").authenticated()
                .pathMatchers("/api/v1/playlists/vip/**").authenticated()
                .pathMatchers("/api/v1/recommendations/vip/**").authenticated()

                // 其他所有接口 - 需要登录认证（由AuthenticationFilter处理JWT验证）
                .anyExchange().permitAll()
            )

            // 异常处理
            .exceptionHandling(exceptions -> exceptions
                .authenticationEntryPoint((exchange, ex) -> {
                    // 认证失败处理（实际由AuthenticationFilter处理）
                    return exchange.getResponse().setComplete();
                })
                .accessDeniedHandler((exchange, denied) -> {
                    // 权限不足处理（实际由相应Filter处理）
                    return exchange.getResponse().setComplete();
                })
            )

            .build();
    }
}
